<template>
    <div class="main" ref="mainContainerRef" @click="selectMainContainer">
        <!-- 菜单容器 -->
        <div class="menu_container" :class="menuContainerClass">
            <div class="menu_title" :style="{ backgroundColor : theme.titleBackgroundColor }">
                <template v-if="logoUrl != ''">
                    <img class="title_logo" :src="logoUrl">
                </template>
                <transition name="menu-title">
                    <h1 :style="{ color : menuTitle.color }" v-if="menuContainerStyle.isShowTitle">{{menuTitle.name}}</h1>
                </transition>
                <span class="cutting_line"></span>
            </div>
            <!--   menu  -->
            <div class="menu_span" :style="{ backgroundColor : theme.menuBackgroundColor }">
                <scoll-bar :is-show-vertical="true" :is-show-horizontal="false">
                    <el-menu
                            :text-color="theme.menuTextColor"
                            :background-color="theme.menuBackgroundColor"
                            :active-text-color="theme.menuActiveTextColor"
                            :collapse-transition="false"
                            :collapse="isCollapse"
                            :default-active="defaultActiveMenu"
                            :unique-opened="true"
                            class="el_menu_list"
                            @select="btSelectMenu">
                        <template v-for="item in menuList" :key=item.index>
                            <el-sub-menu :index="item.index" v-if="item.children.length > 0">
                                <template #title>
                                    <i :class="item.icon" class="menu_icon"></i>
                                    <span>{{item.menuName}}</span>
                                </template>
                                <template v-if="item.children.length > 0">
                                    <el-menu-item-group v-for="childItem in item.children" :key=childItem.index>
                                        <el-menu-item :index="childItem.index">{{childItem.menuName}}</el-menu-item>
                                    </el-menu-item-group>
                                </template>
                            </el-sub-menu>
                            <el-menu-item :index="item.index" v-else>
                                <i :class="item.icon" class="menu_icon"></i>
                                <template #title>{{item.menuName}}</template>
                            </el-menu-item>
                        </template>
                    </el-menu>
                </scoll-bar>
            </div>
        </div>
        <!-- 右侧容器 -->
        <div class="main_container" :class="mainContainerClass">
            <div class="main_top">
                <div class="main_top_left" :style="{ color : theme.btChangeMenuSpan }">
                    <div class="bt_change_menu" @click="changeMenuPanel">
                        <div v-show="isMenuFold.indent">
                            <i class="fas fa-indent"></i>
                        </div>
                        <div v-show="isMenuFold.outdent">
                            <i class="fas fa-outdent"></i>
                        </div>
                    </div>
                    <div class="bt_change_menu_mobile" @click="mobileChangeMenuPanel">
                        <i class="fas fa-bars"></i>
                    </div>
                    <div>
                        <div class="my_crumb_span">
                            <el-breadcrumb separator="/">
                                <template>
                                    <el-breadcrumb-item v-for="item in breadcrumbList" :key="item.index">
                                        {{item.menuName}}
                                    </el-breadcrumb-item>
                                </template>
                            </el-breadcrumb>
                        </div>
                    </div>
                </div>

                <div class="main_top_right">
                    <!-- 还需要判断键盘事件 -->
                    <!-- <div class="main_top_bt" @click="btFullWindow">
                        <span v-show="isFullWindow">
                            <i class="fas fa-compress"></i>
                        </span>
                        <span v-show="!isFullWindow">
                            <i class="fas fa-expand"></i>
                        </span>
                    </div> -->
                    <div class="main_top_name">
                        <span>
                            {{user.nickname}}
                        </span>
                    </div>
                    <el-popover
                            placement="top"
                            width="80px"
                            trigger="click"
                            popper-class="popover_msg_span">
                        <div class="msg_popover">
                            <div class="popover_msg_list">
                                <div class="popover_msg_item" @click="changePassword">修改密码</div>
                            </div>
                            <div class="popover_msg_item login_out" @click="loginOut">退出登录</div>
                        </div>
                        <template #reference>
                            <div class="head_span">
                                <img :src="avatarUrl">
                            </div>
                        </template>
                    </el-popover>
                </div>
            </div>
            <div class="menu_tab_span">
                <cross-slip :scrollHeight=3 arrowColor="#409EFF" sliderColor="#409EFF" activeSliderColor="#409EFF">
                    <div class="tag_span">
                        <template v-for="item in menuTagList" :key="item.menuId">
                            <el-tag class="tag_item" type="success" :effect="item.effect" :closable="item.closable"
                            @click="btSelectMenu(item.index)"
                            @close="closeMenuTag(item.index)" 
                            @contextmenu.prevent="rightSelectTag($event, item.index)" size="small">
                            <span v-show="item.isSelect">
                                <i class="fas fa-circle" ></i>
                            </span>
                            {{item.menu.menuName}}
                            </el-tag>
                        </template>
                    </div>
                </cross-slip>
            </div>
            <div class="show_main">
                <router-view v-slot="{Component}">
                    <transition :name="viewTransitionName">
                        <component :is="Component"/>
                    </transition>
                </router-view>
            </div>
        </div>
    </div>
    <el-dialog v-model="passwordOption.show" title="修改密码"
        width="520px"
        :close-on-click-modal="false"
        :close-on-press-escape="false"
        :before-close="passwordBeforeClose"
        @close="passwordClose">
        <el-form
            label-width="100px"
            :model="passwordForm"
            :rules="passwordRules"
            style="max-width: 520px"
            ref="passwordRef">
            <el-form-item label="旧密码" prop="oldPassword">
                <el-input v-model="passwordForm.oldPassword" 
                placeholder="请输入旧密码"
                type="password"
                :clearable="true"/>
            </el-form-item>
            <el-form-item label="新密码" prop="newPassword">
                <el-input v-model="passwordForm.newPassword" 
                placeholder="包含数字、字母和,@_.特殊符号两两组合6-16个字符"
                type="password"
                :clearable="true"/>
            </el-form-item>
            <el-form-item label="确认新密码" prop="confirmPassword">
                <el-input v-model="passwordForm.confirmPassword" 
                placeholder="请输入确认密码"
                type="password"
                :clearable="true"/>
            </el-form-item>
        </el-form>
        <template #footer>
        <span class="dialog-footer">
            <el-button @click="passwordBeforeClose">取消</el-button>
            <el-button type="primary" @click="saveChangePassword">
            保存
            </el-button>
        </span>
        </template>
    </el-dialog>
    <transition name="tag-operate">
        <div class="tag_operate_span" v-if="tagOperateOption.isShow"
        :style="{'top': tagOperateOption.top, 
        'left': tagOperateOption.left}">
            <div class="tag_operate_item" v-for="item in tagOperateList" @click="btTagOperate(item.type)">
                <i :class="item.icon"></i>
                <span>{{item.text}}</span>
            </div>
        </div>
    </transition>
    
</template>

<script>
import ScollBar from '@/components/scroll-bar.vue';
import CrossSlip from '@/components/cross-slip.vue';

import {tool} from "@/js/tool.js";
import avatarImage from '@/resources/avatar.png';
import logoImage from '@/resources/login/logo.png'

import { NavigationFailureType, isNavigationFailure } from 'vue-router'
import { ElMessage } from 'element-plus'

const SESSION_STORAGE_SELECT_MENU_KEY = "selectMenu";
const SESSION_STORAGE_SELECT_MENU_TAG = "selectMenuTag";
const PASSWORD_VERIFY = /^(?![0-9]+$)(?![a-zA-Z]+$)(?![\\._@,]+$)[0-9A-Za-z\\._@,]{6,16}$/;
const SCREEN_SIZE_MINI = 720;

//vue对象
let mainApp = null;

/**
 * 操作浏览器的后退或者前进按钮时触发事件
 * 
 * @auth zhouhui
 * @since 1.0.0
 */
window.onpopstate = function(event){
    const curUrl = mainApp.$route.fullPath;
    let index = getMenuIndexByUrl(mainApp, curUrl);
    setMenuSelect(mainApp, index, true);
}

export default {
    name: "mainView",
    data: function(){

        const obj = this;
        const confirmPasswordValidator = function(rule, value, callback){
            if(!value){
                callback(new Error('请输入确认密码'));
            }else if(obj.passwordForm.newPassword != value){
                callback(new Error('新密码和确认密码不一致'));
            }else{
                callback();
            }
        }

        return {
            theme: {
                titleBackgroundColor: "#353b40",                //标题背景颜色
                menuBackgroundColor: "#545c64",                 //菜单背景颜色
                menuTextColor: "#ffffff",                       //菜单文字颜色
                menuActiveTextColor: "#409EFF",                 //菜单选中文字颜色
                btChangeMenuSpan: "#303133",                    //折叠菜单按钮颜色
            },
            logoUrl: logoImage,                                 //logo的url
            avatarUrl: avatarImage,                             //头像的url
            menuTitle: {
                name: "系统管理",                                //菜单标题名称
                color: "#ffffff"                                //菜单标题颜色
            },
            user: null,
            isMenuFold: {
                outdent: true,
                indent: false
            },
            isCrumbHomePage: false,
            isCollapse: false,
            topSearchIsShow: false,
            menuContainerClass: {
                menu_container_min: false,
                menu_container_max: true,
                menu_move_init: false,                          //控制初始化时不进行动画演示
                menu_move_show: false,                          //小屏幕菜单显示
                menu_move_hide: false                           //小屏幕菜单隐藏
            },
            mainContainerClass: {
                main_container_min: true,
                main_container_max: false
            },
            menuContainerStyle: {
                isShowTitle: true,
            },
            isFullWindow: false,
            preRouterTo: "",
            viewTransitionName: "",                             //内容切换的动画效果

            menuList: [],                                       //菜单列表
            menuMap: {},
            defaultActiveMenu : "1",
            menuTagList: [],
            breadcrumbList: [],

            screenType: 0,                                      //屏幕类型，0、PC；1、小屏幕

            passwordOption: {
                show: false
            },
            passwordForm: {
                oldPassword: null,
                newPassword: null,
                confirmPassword: null
            },
            passwordRules: {
                oldPassword: [
                    { required: true, message: '请填写旧密码', trigger: 'blur' }  
                ],
                newPassword: [
                    { required: true, trigger: 'blur', validator: passwordValidator }
                ],
                confirmPassword: [
                    { required: true, trigger: 'blur', validator: confirmPasswordValidator }
                ]
            },
            tagOperateList: [
                {text: '关闭当前', icon: 'fa-solid fa-xmark', type: 1},
                {text: '关闭其它', icon: 'fa-regular fa-circle-xmark', type: 2},
                {text: '关闭所有', icon: 'fa-regular fa-circle-xmark', type: 3},
            ],
            tagOperateOption: {
                isShow: false,
                top: '0px',
                left: '0px',
                selectTag: null
            }
        }
    },
    methods : {
        selectMainContainer: function(){
            this.tagOperateOption.isShow = false;
        },
        btSelectMenu: function(index){
            setMenuSelect(this, index, true);
        },
        toHomePage: function(){
            
        },
        closeMenuTag: function(index){
            this.tagOperateOption.isShow = false;
            for(let i=0; i<this.menuTagList.length; i++){
                let item = this.menuTagList[i];
                if(item.index == index){
                    if(item.isSelect){
                        setMenuSelect(this, this.menuTagList[i - 1].index, true);
                    }
                    this.menuTagList.splice(i,1);
                }
            }
            //存储到session中
            localStorage.setItem(SESSION_STORAGE_SELECT_MENU_TAG, JSON.stringify(this.menuTagList));
        },
        rightSelectTag: function(e, index){
            this.tagOperateOption.isShow = true;
            this.tagOperateOption.top = e.clientY + "px";
            this.tagOperateOption.left = e.clientX + 10 + "px";
            this.tagOperateOption.selectTag = index;
        },
        btTagOperate: function(type){
            const index = this.tagOperateOption.selectTag;
            if(type == 1){
                //关闭当前
                if(index != 1){
                    this.closeMenuTag(index);
                }
            }else if(type == 2){
                //关闭其它
                const temp = new Array();
                for (let i = 0; i < this.menuTagList.length; i++) {
                    let item = this.menuTagList[i];
                    if(i == 0){
                        temp.push(item);
                    }else{
                        if(item.index == index){
                            temp.push(item);
                        }
                    }
                }
                this.menuTagList = temp;
                setMenuSelect(this, this.menuTagList[this.menuTagList.length - 1].index, true);
            }else if(type == 3){
                //关闭所有
                const temp = new Array();
                for (let i = 0; i < this.menuTagList.length; i++) {
                    let item = this.menuTagList[i];
                    if(item.index == '1'){
                        temp.push(item);
                    }
                }
                this.menuTagList = temp;
                setMenuSelect(this, this.menuTagList[0].index, true);
            }
            this.tagOperateOption.isShow = false;
        },
        changeMenuPanel: function(){
            if(this.isMenuFold["outdent"]){
                //执行折叠菜单
                this.isMenuFold["outdent"] = false;
                this.isMenuFold["indent"] = true;
                this.isCollapse = true;
                this.menuContainerStyle.isShowTitle = false;
                this.menuContainerClass.menu_container_min = true;
                this.menuContainerClass.menu_container_max = false;

                this.mainContainerClass = {
                    main_container_min: false,
                    main_container_max: true
                };
            }else{
                //执行展开菜单
                this.isMenuFold["outdent"] = true;
                this.isMenuFold["indent"] = false;
                this.isCollapse = false;
                this.menuContainerStyle.isShowTitle = true;
                this.menuContainerClass.menu_container_min = false;
                this.menuContainerClass.menu_container_max = true;

                this.mainContainerClass = {
                    main_container_min: true,
                    main_container_max: false
                };
            }
        },
        mobileChangeMenuPanel: function(){
            //移动端
            this.isMenuFold["outdent"] = true;
            this.isMenuFold["indent"] = false;
            this.isCollapse = false;
            this.menuContainerStyle.isShowTitle = true;
            this.menuContainerClass.menu_container_min = false;
            this.menuContainerClass.menu_container_max = true;

            this.mainContainerClass = {
                main_container_min: true,
                main_container_max: false
            };
            if(this.menuContainerClass.menu_move_init) {
                this.menuContainerClass.menu_move_show = true;
                this.menuContainerClass.menu_move_hide = false;
                this.menuContainerClass.menu_move_init = false;
            }else{
                if(!this.menuContainerClass.menu_move_show){
                    this.menuContainerClass.menu_move_show = true;
                    this.menuContainerClass.menu_move_hide = false;
                }else{
                    this.menuContainerClass.menu_move_show = false;
                    this.menuContainerClass.menu_move_hide = true;
                }
            }
        },
        loginOut: function () {
            //注销
            logOut();
            localStorage.clear();
            this.$router.push({ path: "/", replace: true }).catch(function () {});
        },
        btFullWindow: function(){
            //是否进行全屏
            if(!this.isFullWindow){
                fullScreen();
                this.isFullWindow = true;
            }else{
                exitFullscreen();
                this.isFullWindow = false;
            }
        },
        changePassword: function(){
            this.passwordOption.show = true;
        },
        passwordBeforeClose: function(){
            passwordCloseTips(this);
        },
        passwordClose: function(){
            this.passwordForm = {
                oldPassword: null,
                newPassword: null,
                confirmPassword: null
            }
            this.$refs["passwordRef"].clearValidate();
        },
        saveChangePassword: function(){
            const obj = this;
            this.$refs["passwordRef"].validate(function(valid){
                if(valid){
                    setChangePassword(obj);
                }
            });
        },
        skipMenuPage: function(curUrl, queryParam){
            let index = getMenuIndexByUrl(this, curUrl);
            setMenuSelect(this, index, true, queryParam);
        }
    },
    provide: function() {
        return {
            skipMenuPage: this.skipMenuPage
        }
    }, 
    created: function() {
        mainApp = this;
        const userStr = localStorage.getItem("user");
        if(userStr){
            this.user = JSON.parse(userStr);
        } 
    },
    mounted: function() {
        getUserMenu(this, function(){});

        calculateScreenSize(this);
    },
    watch : {
        '$route' (to, from) {
            const toDepth = to.path.split('/').length;
            const fromDepth = from.path.split('/').length;
            this.viewTransitionName = toDepth < fromDepth ? 'slide-right' : 'slide-left';
        },
        screenType(newValue, oldValue) {
            screenSizeChangeInit(this);
        }
    },
    components : {
        ScollBar,
        CrossSlip
    }
}

/**
 * 计算屏幕大小
 * @param app vue对象
 * 
 * @auth zhouhui
 * @since 1.0.0
 */
function calculateScreenSize(app) {
    const width = app.$refs['mainContainerRef'].offsetWidth;
    if(width <= SCREEN_SIZE_MINI){
        app.screenType = 1;
    }else {
        app.screenType = 0;
    }
}
/**
 * 监听屏幕大小改变 
 */
window.addEventListener('resize', function(){
    if(mainApp != null){
        calculateScreenSize(mainApp); 
    }
});

/**
 * 屏幕类型改变进行数据初始化
 * @param app vue对象
 * 
 * @auth zhouhui
 * @since 1.0.0
 */
function screenSizeChangeInit(app) {
    if(app.screenType == 0){
        //pc屏幕
        app.menuContainerClass.menu_move_hide = false;
        app.menuContainerClass.menu_move_show = false;
    }else {
        //小屏幕
        app.menuContainerClass.menu_move_init = true;
        app.menuContainerClass.menu_move_hide = false;
        app.menuContainerClass.menu_move_show = false;
    }
}

/**
 * 全屏显示
 */
function fullScreen() {
    var element = document.documentElement;
    if (element.requestFullscreen) {
        element.requestFullscreen();
    } else if (element.msRequestFullscreen) {
        element.msRequestFullscreen();
    } else if (element.mozRequestFullScreen) {
        element.mozRequestFullScreen();
    } else if (element.webkitRequestFullscreen) {
        element.webkitRequestFullscreen();
    }
}
/**
 * 取消全屏显示
 */
function exitFullscreen() {
    if (document.exitFullscreen) {
        document.exitFullscreen();
    } else if (document.msExitFullscreen) {
        document.msExitFullscreen();
    } else if (document.mozCancelFullScreen) {
        document.mozCancelFullScreen();
    } else if (document.webkitExitFullscreen) {
        document.webkitExitFullscreen();
    }
}

/**
 * 获取用户能够显示的菜单
 * @param app vue对象
 * @param callback 成功获取之后进行回调
 * 
 * @auth zhouhui
 * @since 1.0.0
 */
function getUserMenu(app,callback){
    //获取菜单
    const getMenuUrl = "/user/menu";
    tool.formJsonRequest(getMenuUrl,{},function(){},
    function(data){
        if(data.code === '0000'){
            app.menuList = data.data;
            setMenuMap(app,app.menuList);
            const selectMenuTag = localStorage.getItem(SESSION_STORAGE_SELECT_MENU_TAG);
            if(selectMenuTag){
                const menuTagList = JSON.parse(selectMenuTag);
                for(let i=0;i<menuTagList.length;i++){
                    app.menuTagList.push(menuTagList[i]);
                }
            }
            const curUrl = mainApp.$route.fullPath;
            let curIndex = getMenuIndexByUrl(mainApp, curUrl);
            if(curIndex){
                //访问的地址存在
                setMenuSelect(app, curIndex, true);
            }else{
                //不存在时，获取之前访问过的地址
                const selectMenuIndex = localStorage.getItem(SESSION_STORAGE_SELECT_MENU_KEY);
                if(selectMenuIndex){
                    setMenuSelect(app, 1, false);
                    setMenuSelect(app, selectMenuIndex, true);
                }else{
                    setMenuSelect(app, 1, true);
                }
            }
            if(callback != null){
                callback();
            }
        }else if(data.code === '0002'){
            app.$alert('没有访问权限！', {
                confirmButtonText: '确定',
                callback: function(){
                }
            });
        }else{
            app.$alert('登录异常，请重新登录！', {
                confirmButtonText: '确定',
                callback: function(){
                    window.location.href = "./index.html";
                }
            });
        }
    });
}

/**
 * 保存修改密码
 * @param app vue对象
 * 
 * @auth zhouhui
 * @since 1.0.0
 */
function setChangePassword(app){
    const url = "/user/changePassword";
    const param = {
        oldPassword: app.passwordForm.oldPassword,
        newPassword: app.passwordForm.newPassword
    }
    tool.formJsonRequest(url,param,function(){},
    function(data){
        if(data.code === '0000'){
            ElMessage({
                showClose: true,
                message: '登录密码修改成功',
                type: 'success',
                onClose: function(){
                    //重新登录
                    app.$router.push("/").catch(function () {});
                    localStorage.clear();
                }
            });
            app.passwordOption.show = false; 
        }else{
            ElMessage({
                showClose: true,
                message: data.message,
                type: 'error'
            });
        }
    });
}

/**
 * 将菜单转成Key-Value的格式。
 * @param app vue对象
 * @param menuList 菜单的列表
 * 
 * @auth zhouhui
 * @since 1.0.0
 */
function setMenuMap(app, menuList){
    for(let i = 0; i < menuList.length; i++){
        let item = menuList[i];
        if(item.children != null && item.children.length > 0){
            setMenuMap(app,item.children);
        }
        app.menuMap[item.index] = item;
    }
}

/**
 * 菜单选择
 * @param app vue对象
 * @param index 菜单的索引
 * @param isSkip 是否需要跳转页面，true跳转；false不跳转
 * @param queryParam 地址栏额外的参数
 *  
 * @auth zhouhui
 * @since 1.0.0
 */
function setMenuSelect(app, index, isSkip, queryParam) {
    if(!queryParam){
        queryParam = {};
    }
    //设置菜单选中项
    app.defaultActiveMenu = index + "";
    //设置TAG标签
    setTagMenuList(app, index);
    //设置面包屑导航
    setBreadcrumbList(app, index);
    //路由跳转
    if(isSkip){
        menuRouter(app, index, queryParam);
    }
}

/**
 * 菜单路由。
 * 存储当前跳转的菜单的index。
 * @param app vue对象
 * @param index 菜单的索引
 * @param queryParam 地址请求参数对象
 * 
 * @auth zhouhui
 * @since 1.0.0
 */
function menuRouter(app, index, queryParam){
    const selectMenu = app.menuMap[index];
    if(selectMenu.menuType == 1){
        //打开新标签页
        window.open(addParamToUrl(selectMenu.menuUrl,queryParam));
    }else{
        let param = {
            menuId: selectMenu.menuId
        }
        for(let item in queryParam){
            param[item] = queryParam[item];
        }
        app.$router.push({
            path: selectMenu.menuUrl,
            query: param,
            replace: false
        })
        .then(complete => {
            //成功
            localStorage.setItem(SESSION_STORAGE_SELECT_MENU_KEY,index);
        })
        .catch(failure => {
            if(isNavigationFailure(failure,NavigationFailureType.duplicated)){

            }else{
                app.$router.push({path: "/error?code=404", replate: true});
            }
        });
    }
}

/**
 * 向地址中拼接参数
 * @param app url 地址信息
 * @param queryParam 参数对象
 * 
 * @auth zhouhui
 * @since 1.0.0
 */
function addParamToUrl(url, queryParam){
    let paramStr = "";
    let index = 0;
    for(let item in queryParam){
        if(index > 0){
            paramStr += "&";
        }
        paramStr += (item + "=" +queryParam[item]);
        index ++;
    }
    if(!paramStr){
        return url;
    }
    if(url.indexOf("?") >= 0){
        url += ( "&" + paramStr ); 
    }else{
        url += ( "?" + paramStr ); 
    }
    return url;
}

/**
 * 设置Tag菜单
 * @param app vue对象
 * @param index 菜单的索引
 * 
 * @auth zhouhui
 * @since 1.0.0
 */
function setTagMenuList(app, index){
    let isClosable = true;
    if(index == 1){
        isClosable = false;
    }
    let isExis = false;
    for(let i=0; i < app.menuTagList.length; i++){
        let item = app.menuTagList[i];
        if(item.index == index){
            item.isSelect = true;
            isExis = true;
        }else{
            item.isSelect = false;
        }
    }
    if(!isExis){
        const selectMenu = app.menuMap[index];
        const menuItem = {
            "menuId": selectMenu.menuId,
            "index": index + "",
            "closable": isClosable,
            "isSelect": true,
            "menu": selectMenu,
        }
        app.menuTagList.push(menuItem);
    }
    //存储到session中
    localStorage.setItem(SESSION_STORAGE_SELECT_MENU_TAG, JSON.stringify(app.menuTagList));
}

/**
 * 设置breadcrumb显示的菜单
 * @param app vue对象
 * @param index 菜单的索引
 * 
 * @auth zhouhui
 * @since 1.0.0
 */
function setBreadcrumbList(app, index){
    app.breadcrumbList = [];
    const keys = (index+"").split("-");
    for(let i=0;i<keys.length;i++){
        let selectMenu = getMenuByMenuId(app, keys[i]);
        app.breadcrumbList.push(selectMenu);
    }
}

/**
 * 根据地址栏的url获取
 * @param app vue对象
 * @param url 地址url
 * 
 * @auth zhouhui
 * @since 1.0.0
 */
function getMenuIndexByUrl(app, url){
    if(!url){
        return null;
    }
    url = url.split("?")[0];
    for(let index in app.menuMap){
        let menu = app.menuMap[index];
        if(menu == null || !menu.menuUrl){
            continue;
        }
        if(url == menu.menuUrl){
            return index;
        }
    }
    return null;
}

/**
 * 密码校验
 * @param rule 
 * @param value 
 * @param callback 
 * 
 * @auth zhouhui
 * @since 1.0.0
 */
function passwordValidator(rule, value, callback){
    if(!value){
        callback(new Error('请输入新密码'));
    }else if(!PASSWORD_VERIFY.test(value)){
        callback(new Error('请包含数字、字母和,@_.特殊符号两两组合6-16个字符'));
    }else{
        callback();
    }
}


/**
 * 根据menu的ID获取menu
 * @param app vue对象
 * @param menuId menu的ID
 * 
 * @auth zhouhui
 * @since 1.0.0
 */
function getMenuByMenuId(app, menuId){
    for(let key in app.menuMap){
        let item = app.menuMap[key];
        if(item.menuId == menuId){
            return item;
        }
    }
}

/**
 * 退出登录
 * @since 1.0.0
 */
function logOut(){
    const url = "/user/logOut";
    tool.formRequest(url, null, null, function (data) {
        
    });
}

/**
 * 弹窗关闭时的提示信息
 * @param app
 */
function passwordCloseTips(app) {
    let confirmMessage = "是否放弃修改密码";
    app.$confirm(confirmMessage).then(function(){
            app.passwordOption.show = false;
    }).catch(function(){

    });
}
</script>

<style>
* {
  padding: 0px 0px 0px 0px;
  margin: 0px 0px 0px 0px;
  font-family: Microsoft YaHei, Heiti SC, tahoma, arial, Hiragino Sans GB,
    "\5B8B\4F53", sans-serif;
}
body,
html {
  width: 100%;
  height: 100%;
}
.main{
    display: flex;
    flex-direction: row;
    width: 100%;
    height: 100%;
    overflow: hidden;
    background: none;
}
.main .menu_container{
    display: flex;
    flex-direction: column;
    height: 100%;
    top: 0px;
    left: 0px;
}

.main .menu_container_min{
    width: 64px;
    transition: width 0.2s;
}
.main .menu_container_max{
    width: 200px;
    transition: width 0.2s;
}


/*--   menu title  --*/
.menu_container .menu_title{
    display: flex;
    flex-direction: row;
    justify-content: center;
    align-items: center;
    width: 100%;
    height: 50px;
    background-color: #3a8ee6;
}

.menu_title .title_logo{
    width: 40px;
    height: 40px;
}
.menu_title h1{
    color: #FFFFFF;
    font-size: 20px;
    font-weight: 400;
    padding: 0px 5px 0px 5px;
    cursor: default;
    white-space: nowrap;
    width: auto;
    overflow: hidden;
}

.menu-title-enter-active{
    transition: opacity 0.5s;
}
.menu-title-leave-active{
    opacity: 0;
}
.menu-title-enter,.menu-title-leave-to{
    opacity: 0;
}

/*--  menu container --*/
.menu_container .menu_span{
    display: flex;
    flex-direction: column;
    width: 100%;
    height: calc(100% - 50px);
}

.menu_span .el_menu_list{
    border: none;
    width: 200px;
}

.menu_span .el-menu--collapse{
    width: calc(100% - 10px);
}

.main_container{
    display: flex;
    flex-direction: column;
    height: 100%;
}
.main .main_container_min{
    width: calc(100% - 200px);
    transition: width 0.2s;
}
.main .main_container_max{
    width: calc(100% - 64px);
    transition: width 0.2s;
}

.el_menu_list .menu_icon{
    width: 24px;
    height: 18px;
    font-size: 18px;
    text-align: center;
    margin-right: 5px;
}
.el_menu_list .fas{
    width: 24px;
    height: 18px;
    font-size: 18px;
    text-align: center;
    margin-right: 5px;
}
.el_menu_list .fab{
    width: 24px;
    height: 18px;
    font-size: 18px;
    text-align: center;
    margin-right: 5px;
}
.el_menu_list .far{
    width: 24px;
    height: 18px;
    font-size: 18px;
    text-align: center;
    margin-right: 5px;
}


/*--    main_top   --*/
.main_container .main_top{
    display: flex;
    flex-direction: row;
    justify-content: space-between;
    width: 100%;
    height: 49px;
    background-color: #ffffff;
    border-bottom: 1px solid #EBEEF5;
    /* box-shadow: 0 1px 1px rgba(0,21,41,0.08); */
}

.main_top .my_crumb_span{
    display: flex;
    flex-direction: row;
    justify-content: center;
    align-items: center;
    width: auto;
    height: 50px;
    font-size: 14px;
    color: #FFFFFF;
    line-height: 50px;
    font-weight: 100;
}
.my_crumb_span .crumb_item_span{
    display: flex;
    flex-direction: row;
    width: auto;
    height: 100%;
}
.my_crumb_span .my_crumb_item{
    color: #909399;
    font-weight: 400;
    cursor: default;
}
.my_crumb_span .crumb_home_page{
    color: #606266;
    font-weight: 600;
    cursor: pointer;
}
.my_crumb_span .crumb_home_page:hover{
    color: #409EFF;
}
.my_crumb_span .crumb_separator{
    color: #909399;
    font-weight: 400;
    padding: 0px 18px 0px 18px;
}
.animation_crumb-enter-active{
    transition: all 3s cubic-bezier(1.0, 0.5, 0.8, 1.0);;
}
.animation_crumb-enter{
     transform: translateX(-10px);
     opacity: 0;
 }
.animation_crumb-enter-to{
    transform: translateX(0px);
    opacity: 1;
}
.animation_crumb-leave-active{
    transition: all 0.3s cubic-bezier(1.0, 0.5, 0.8, 1.0);
}
.animation_crumb-leave-to{
    transform: translateX(10px);
    opacity: 0;
}

/*--    main_top_left    --*/
.main_top .main_top_left{
    display: flex;
    min-width: 100px;
    height: 100%;
}
/*--    main_top_right    --*/
.main_top .main_top_right{
    display: flex;
    justify-content: flex-end;
    align-items: center;
    min-width: 100px;
    height: 100%;
}
.main_top_right .main_top_name{
    display: flex;
    justify-content: center;
    align-items: center;
    min-width: 30px;
    height: 100%;
    padding: 0px 5px 0px 0px;
    margin-right: 0px;
    font-size: 16px;
    font-weight: 200;
    color: #606266;
    cursor: default;
}
.main_top_right .main_top_bt{
    display: flex;
    justify-content: center;
    align-items: center;
    min-width: 30px;
    height: 100%;
    padding: 0px 5px 0px 0px;
    margin-right: 0px;
    font-size: 20px;
    font-weight: 100;
    color: #606266;
    cursor: pointer;
}
@keyframes chane-input-width {
    0%{
        width: 0px;
    }
    100%{
        width: 100px;
    }
}

.top_search_span input::-webkit-input-placeholder { /* WebKit browsers */
    color: #C0C4CC;
}

.top_search_span input:-moz-placeholder { /* Mozilla Firefox 4 to 18 */
    color: #C0C4CC;
}

.top_search_span input::-moz-placeholder { /* Mozilla Firefox 19+ */
    color: #C0C4CC;
}

.top_search_span input:-ms-input-placeholder { /* Internet Explorer 10+ */
    color: #909399;
}

.search_menu_span{
    width: 100%;
    height: auto;
    list-style: none;
}
.search_menu_span li{
    list-style: none;
    display: flex;
    flex-direction: row;
    width: 100%;
    height: 30px;
    line-height: 30px;
    font-family: Microsoft YaHei,Heiti SC,tahoma,arial,Hiragino Sans GB,"\5B8B\4F53",sans-serif;
    cursor: pointer;
}

.search_menu_span li .search_menu_span_symbol{
    margin-right: 12px;
    margin-left: 12px;
}

.main_top_right .head_span{
    width: 38px;
    height: 38px;
    border-radius: 8px;
    overflow: hidden;
    cursor: pointer;
    margin-right: 30px;
    border: 2px solid #3a8ee6;
}
.popover_msg_span{
    min-width: 100px;
    padding: 0px;
}
.msg_popover{
    display: flex;
    flex-direction: column;
    width: 100%;
    height: 100%;
    font-size: 14px;
}
.msg_popover .popover_msg_list{
    display: flex;
    flex-direction: column;
    width: 100%;
    height: auto;
    margin-top: 10px;
    border-bottom: 1px solid #EBEEF5;
}
.popover_msg_item{
    width: 100%;
    height: 30px;
    text-align: center;
    line-height: 30px;
    cursor: pointer;
    margin-bottom: 5px;
    color: #606266;
}
.msg_popover .login_out{
    margin-top: 5px;
}
.popover_msg_item:hover{
    background-color: rgb(217, 236, 255);
    color: rgb(102, 177, 255);
}

.head_span img{
    width : 100%;
    height: 100%;
}
.main_top_left .bt_change_menu{
    display: flex;
    justify-content: center;
    align-items: center;
    width: 50px;
    height: 100%;
    font-size: 24px;
    cursor: pointer;
}
.main_top_left .bt_change_menu_mobile {
    display: none;
    justify-content: center;
    align-items: center;
    width: 50px;
    height: 100%;
    font-size: 24px;
    cursor: pointer;
}

.main_container .menu_tab_span{
    display: flex;
    flex-direction: row;
    width: 100%;
    height: 35px;
    overflow: hidden;
    border-bottom: 1px solid #EBEEF5;
    box-shadow: 0 1px 4px rgba(0,21,41,0.08);
    z-index: 10;
}
.menu_tab_span .tag_span{
    display: flex;
    width: auto;
    height: 35px;
    flex-direction: row;
    justify-content: center;
    align-items: center;
    margin-left: 10px;
}
.tag_span .tag_item{
    margin-right: 10px;
    cursor: pointer;
}
.el-tag.tag_item.tag_selected{
    background-color: #66CDAA;
    border-color: #66CDAA;
    color: #FFFFFF;
}
.el-tag.tag_item.tag_unselected{
    background-color: #FFFFFF;
    border-color: #66CDAA;
    color: #66CDAA;
}
.el-tag.tag_item.tag_unselected .el-tag__close{
    color: #66CDAA;
}

.el-tag.tag_item.tag_unselected .el-tag__close:hover{
    color: #FFFFFF;
    background-color: #66CDAA;
}

.el-tag.tag_item.tag_selected .el-tag__close:hover{
    color: #FFFFFF;
    background-color: #4abf97;
}
.tag_operate_span {
    position: absolute;
    display: flex;
    flex-direction: column;
    top: 0px;
    left: 0px;
    width: 120px;
    min-height: 60px;
    z-index: 100;
    padding: 4px 0px 4px 0px;
    background: var(--el-bg-color-overlay);
    border: var(--el-border-color-light);
    border-radius: var(--el-popover-border-radius);
    box-shadow: var(--el-box-shadow-light);
    font-size: 14px;
    color: #909399;
}
.tag-operate-enter-active,
.tag-operate-leave-active {
    transition: opacity 0.5s ease;
}

.tag-operate-enter-from,
.tag-operate-leave-to {
  opacity: 0;
}

.tag_operate_span .tag_operate_item{
    display: flex;
    flex-direction: row;
    flex-wrap: nowrap;
    justify-content: space-around;
    align-items: center;
    width: calc(100% - 28px);
    height: 20px;
    padding: 8px 14px 8px 14px;
    cursor: pointer;
}
.tag_operate_span .tag_operate_item:hover {
    background: #e9e9eb;
}

.main_container .show_main{
    width: 100%;
    height: calc(100% - 70px);
    overflow: hidden;
    /*background: #8cc5ff;*/
}

.slide-right-enter-active {
    transition: all .2s ease;
}
.slide-right-leave-active {
    transition: all .2s cubic-bezier(1.0, 0.5, 0.8, 1.0);
}
.slide-right-enter, .slide-right-leave-to {
    transform: translateX(10px);
    opacity: 0;
}

.slide-left-enter-active {
    transition: all .2s ease;
}
.slide-left-leave-active {
    transition: all .2s cubic-bezier(1.0, 0.5, 0.8, 1.0);
}
.slide-left-enter, .slide-left-leave-to{
    transform: translateX(10px);
    opacity: 0;
}

.web_container{
    width: 100%;
    height: 100%;
}

.my_scroller_style .is-scrolling-none::-webkit-scrollbar{
    width: 8px;
    background-color: #F5F5F5;
}
.my_scroller_style .is-scrolling-none::-webkit-scrollbar-thumb{
    border-radius: 2px;
    background-color: rgb(84, 92, 100);
}
.my_scroller_style .is-scrolling-none::-webkit-scrollbar-track{
    border-radius: 2px;
    background-color: #F5F5F5;
}

.main .menu_move_init {
    left: -230px;
}

.main .menu_move_show {
    left: 0px;
    animation: menuMoveShow;
    animation-duration: 0.5s;
    animation-timing-function: cubic-bezier(0.645, 0.045, 0.355, 1)
}

@keyframes menuMoveShow {
    0% {
        left: -230px;
    }
    100% {
        left: 0px;
    }
}

.main .menu_move_hide {
    left: -230px;
    animation: menuMoveHide;
    animation-duration: 0.5s;
    animation-timing-function: cubic-bezier(0.645, 0.045, 0.355, 1)
}

@keyframes menuMoveHide {
    0% {
        left: 0px;
    }
    100% {
        left: -230px;
    }
}


@media screen and (max-width: 720px) {
    .main .menu_container{
        position: fixed;
        top: 85px;
        height: calc(100% - 85px);
        z-index: 999;
    }
    .main .main_container_min{
        width: 100%;
    }
    .main .main_container_max{
        width: 100%;
    }
    .main_top_left .bt_change_menu_mobile{
        display: flex;
    }
    .main_top_left .bt_change_menu {
        display: none;
    }
}
</style>